#include <reg51.h>
#include <intrins.h>

// 硬件引脚定义
sbit Trig = P3^0;  // 触发信号输出
sbit Echo = P3^2;  // 回波信号输入（接INT0）
sbit LED = P1^0;   // 状态指示LED

// 全局变量
unsigned int time = 0;       // 回波高电平持续时间（μs）
unsigned int distance = 0;   // 测量距离（cm）
bit flag = 0;                // 测量完成标志

// 延时函数（约10μs）
void delay10us() {
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
}

// 定时器0初始化（用于计时，1μs精度）
void Timer0Init() {
    TMOD &= 0xF0;  // 清除定时器0配置
    TMOD |= 0x01;  // 方式1，16位定时器
    TH0 = 0;       // 初值0，从0开始计数
    TL0 = 0;
    ET0 = 1;       // 允许定时器0中断
    EA = 1;        // 允许总中断
}

// 外部中断0初始化（双边沿触发）
void Int0Init() {
    IT0 = 0;       // 电平触发模式（实际通过软件模拟双边沿）
    EX0 = 1;       // 允许外部中断0
    EA = 1;        // 允许总中断
}

// 发送超声波触发信号
void SendTrig() {
    Trig = 0;
    _nop_();
    Trig = 1;
    delay10us();   // 至少10μs高电平
    Trig = 0;
}

// 外部中断0服务程序（捕捉Echo上升/下降沿）
void Int0Handler() interrupt 0 {
    if (Echo == 1) {  // 上升沿：开始计时
        time = 0;
        TH0 = 0;
        TL0 = 0;
        TR0 = 1;      // 启动定时器
    } else {          // 下降沿：停止计时
        TR0 = 0;      // 停止定时器
        time = (TH0 << 8) | TL0;  // 计算总时间（μs）
        flag = 1;     // 置位测量完成标志
    }
}

// 定时器0中断服务程序（超时处理，防止无限等待）
void Timer0Handler() interrupt 1 {
    TR0 = 0;          // 停止定时器
    flag = 0;         // 超时，无效测量
    TH0 = 0;
    TL0 = 0;
    LED = 1;          // 超时指示
}

void main() {
    Timer0Init();
    Int0Init();
    LED = 0;
    while(1) {
        SendTrig();           // 发送触发信号
        // 等待测量完成（最多等待38ms，对应最大测距约6.5m）
        while(!flag);
        flag = 0;
        
        // 计算距离（声速≈340m/s=0.034cm/μs，往返需除以2）
        distance = time * 0.034 / 2;
        
        // 简单处理：距离小于50cm时点亮LED
        LED = (distance < 50) ? 0 : 1;
        
        // 延时一段时间再进行下一次测量（避免信号干扰）
        {
            unsigned int i, j;
            for(i=0; i<1000; i++)
                for(j=0; j<112; j++);
        }
    }
}
